package expression;

import echecs.Coups;
import echecs.Etat;
import echecs.Echiquier;
import echecs.Echiquier.Case;
import echecs.Pieces.Piece;
import java.util.ArrayList;
import static echecs.Pieces.Piece.*;

public class ExpressionBase {

    public static Impression Impression;
    public static CaseSuivante CaseSuivante;
    public static ExisteCaseSuiv ExisteCaseSuiv;
    public static PieceCouleurEtudiee PieceCouleurEtudiee;
    public static EstPion EstPion;
    public static EstRoiCavalier EstRoiCavalier;
    public static EstTourFouDame EstTourFouDame;
    public static NewArrayListCoups NewArrayListCoups;
    public static DirSuivante DirSuivante;
    public static DistSuivante DistSuivante;
    public static InitDist InitDist;
    public static InitIndex InitIndex;
    public static InitDir InitDir;
    public static AjoutCoupsListe AjoutCoupsListe;
    public static NewCoups NewCoups;
    public static EstPionDep EstPionDep;
    public static EstFinDirPion EstFinDirPion;
    public static ExamineEchecs ExamineEchecs;
    public static PieceCouleurQuiJoue PieceCouleurQuiJoue;
    public static ArrVide ArrVide;
    public static EstCaseArrOccup EstCaseArrOccup;
    public static PieceCouleurOpp PieceCouleurOpp;
    public static ExisteDirSuiv ExisteDirSuiv;

    public ExpressionBase() {
        CaseSuivante = new CaseSuivante();
        Impression = new Impression();
        ExisteCaseSuiv = new ExisteCaseSuiv();
        PieceCouleurEtudiee = new PieceCouleurEtudiee();
        AjoutCoupsListe = new AjoutCoupsListe();
        NewCoups = new NewCoups();
        EstPion = new EstPion();
        EstRoiCavalier = new EstRoiCavalier();
        EstTourFouDame = new EstTourFouDame();
        NewArrayListCoups = new NewArrayListCoups();
        DirSuivante = new DirSuivante();
        DistSuivante = new DistSuivante();
        InitDist = new InitDist();
        InitIndex = new InitIndex();
        InitDir = new InitDir();
        EstPionDep = new EstPionDep();
        EstFinDirPion = new EstFinDirPion();
        ExamineEchecs = new ExamineEchecs();
        PieceCouleurQuiJoue = new PieceCouleurQuiJoue();
        ArrVide = new ArrVide();
        EstCaseArrOccup = new EstCaseArrOccup();
        PieceCouleurOpp = new PieceCouleurOpp();
        ExisteDirSuiv = new ExisteDirSuiv();
    }

    public class ExisteDirSuiv implements Expression {

        @Override
        public Object f(Etat etat) {
            int pIndexDir = etat.getDirIndex();
            Piece pPieceDep = etat.getPieceDep();
            return pIndexDir < pPieceDep.getDeplacement().length;
        }
    }

    public class PieceCouleurOpp implements Expression, Echiquier {

        @Override
        public Object f(Etat etat) {
            Piece pPieceDep = etat.getPieceDep();
            int pDist = etat.getDist();
            int pIndexDep = etat.getIndexDep();
            int pIndexDir = etat.getDirIndex();
            Piece[] PIECES = etat.getPieces();
            return pPieceDep.getCouleur() != PIECES[ECHIQUIER[TO_ECHIQUIER[pIndexDep] +
                    pDist * pPieceDep.getDeplacement()[pIndexDir]]].getCouleur();
        }
    };

    public class EstCaseArrOccup implements Expression, Echiquier {

        @Override
        public Object f(Etat etat) {
            Piece pPieceDep = etat.getPieceDep();
            int pDist = etat.getDist();
            int pIndexDep = etat.getIndexDep();
            int pIndexDir = etat.getDirIndex();
            Piece[] PIECES = etat.getPieces();
            return ECHIQUIER[TO_ECHIQUIER[pIndexDep] +
                    pDist * pPieceDep.getDeplacement()[pIndexDir]] != -1 && PIECES[ECHIQUIER[TO_ECHIQUIER[pIndexDep] +
                    pDist * pPieceDep.getDeplacement()[pIndexDir]]] != null;
        }
    };

    public class ArrVide implements Expression, Echiquier {

        @Override
        public Object f(Etat etat) {
            Piece pPieceDep = etat.getPieceDep();
            int pDist = etat.getDist();
            int pIndexDep = etat.getIndexDep();
            int pIndexDir = etat.getDirIndex();
            Piece[] PIECES = etat.getPieces();
            return (Boolean) (ECHIQUIER[TO_ECHIQUIER[pIndexDep] +
                    pDist * pPieceDep.getDeplacement()[pIndexDir]] != -1 && PIECES[ECHIQUIER[TO_ECHIQUIER[pIndexDep] +
                    pDist * pPieceDep.getDeplacement()[pIndexDir]]] == null);
        }
    };

    public class PieceCouleurQuiJoue implements Expression {

        @Override
        public Object f(Etat etat) {
            Piece pPieceDep = etat.getPieceDep();
            return (Boolean) (pPieceDep != null && pPieceDep.getCouleur() == etat.getCouleur());
        }
    }

    public class ExamineEchecs implements Expression {

        @Override
        public Object f(Etat etat) {
            return (Boolean) etat.getExamineEchecs();
        }
    }

    public class EstFinDirPion implements Expression {

        @Override
        public Object f(Etat etat) {
            return (Boolean) (etat.getDirIndex() <= 2);
        }
    }

    public class EstPionDep implements Expression {

        @Override
        public Object f(Etat etat) {
            int pIndexDep = etat.getIndexDep();
            Piece pPieceDep = etat.getPieceDep();
            return (Boolean) (Case.valeur(pIndexDep).estARangee2() && pPieceDep.getCouleur() == Couleur.BLANC ||
                    Case.valeur(pIndexDep).estARangee7() && pPieceDep.getCouleur() == Couleur.NOIR);
        }
    }

    public class Impression implements Expression {

        @Override
        public Object f(Etat etat) {
            Piece pPieceDep = etat.getPieceDep();
            System.out.println(pPieceDep + ":" + Case.valeur(etat.getIndexDep()) + ",");
            return etat;
        }
    }

    public class CaseSuivante implements Expression {

        @Override
        public Object f(Etat etat) {
            etat.incIndex();
            return etat;
        }
    }

    public class EstPion implements Expression {

        @Override
        public Object f(Etat etat) {
            Piece pPieceDep = etat.getPieceDep();
            return (Boolean) (pPieceDep.equals(PION_BLANC) || pPieceDep.equals(PION_NOIR));
        }
    }

    public class EstRoiCavalier implements Expression {

        @Override
        public Object f(Etat etat) {
            Piece pPieceDep = etat.getPieceDep();
            return (Boolean) (pPieceDep.equals(ROI_BLANC) || pPieceDep.equals(ROI_NOIR) ||
                    pPieceDep.equals(CAVALIER_BLANC) || pPieceDep.equals(CAVALIER_NOIR));
        }
    }

    public class EstTourFouDame implements Expression {

        @Override
        public Object f(Etat etat) {
            Piece pPieceDep = etat.getPieceDep();
            assert pPieceDep != null;
            return (Boolean) (pPieceDep.equals(FOU_BLANC) || pPieceDep.equals(FOU_NOIR) ||
                    pPieceDep.equals(TOUR_BLANCHE) || pPieceDep.equals(TOUR_NOIRE) ||
                    pPieceDep.equals(DAME_BLANCHE) || pPieceDep.equals(DAME_NOIRE));
        }
    }

    public class ExisteCaseSuiv implements Expression, Echiquier {

        @Override
        public Object f(Etat etat) {
            return (Boolean) (etat.getIndexDep() < NB_COLONNES * NB_RANGEES);
        }
    }

    public class PieceCouleurEtudiee implements Expression {

        @Override
        public Object f(Etat etat) {
            Piece pPieceDep = etat.getPieces()[etat.getIndexDep()];
            etat.setPieceDep(pPieceDep);
            return (Boolean) (pPieceDep != null && pPieceDep.getCouleur() == etat.getCouleur());
        }
    }

    public class NewArrayListCoups implements Expression {

        @Override
        public Object f(Etat etat) {
            etat.setListeCoupsPart(new ArrayList<Coups>());
            return etat;
        }
    }

    public class DirSuivante implements Expression {

        @Override
        public Object f(Etat etat) {
            etat.incDirIndex();
            return etat;
        }
    }

    public class DistSuivante implements Expression {

        @Override
        public Object f(Etat etat) {
            etat.incDistIndex();
            return etat;
        }
    }

    public class InitDist implements Expression {

        @Override
        public Object f(Etat etat) {
            etat.setDist(1);
            return etat;
        }
    }

    public class InitIndex implements Expression {

        @Override
        public Object f(Etat etat) {
            etat.setDist(1);
            etat.setDirIndex(0);
            return etat;
        }
    }

    public class InitDir implements Expression {

        @Override
        public Object f(Etat etat) {
            etat.setDirIndex(0);
            return etat;
        }
    }

    public class AjoutCoupsListe implements Expression {

        public void exec() {
        }

        @Override
        public Object f(Etat etat) {
            etat.getListeCoups().addAll(etat.getListeCoupsPart());
            return etat;
        }
    }

    public class NewCoups implements Expression, Echiquier {

        @Override
        public Object f(Etat etat) {
            int pIndexArr = ECHIQUIER[TO_ECHIQUIER[etat.getIndexDep() +
                    etat.getDist() * etat.getPieceDep().getDeplacement()[etat.getDirIndex()]]];
            etat.setIndexArr(pIndexArr);
            etat.getListeCoupsPart().add(new Coups(etat.getIndexDep(), etat.getPieceDep(), pIndexArr));
            return etat;
        }
    }
}








